/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.deployment.helper;

import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.uml2.uml.DeployedArtifact;
import org.eclipse.uml2.uml.Deployment;
import org.eclipse.uml2.uml.DeploymentTarget;
import org.eclipse.uml2.uml.Element;

import com.cea.papyrus.core.helper.GraphEdgeHelper;
import com.cea.papyrus.core.helper.NodeHelper;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.Diagram;
import com.cea.papyrus.diagraminterchange2.di2.GraphEdge;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Defines management of deployments.
 * 
 * @author Gilles Cannenterre
 * @since 15 janv. 07
 */
public class EdgeDeploymentHelper extends GraphEdgeHelper{

	/**
	 * The channel.
	 */
	private int channel = 203;

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.helper.GraphEdgeHelper#connect(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param target 
	 * @param link 
	 * @param source 
	 * 
	 * @return 
	 */
	@Override
	public boolean connect(Element source, Element target, Element link) {
		Debug.debug(this,"connect link", channel);
		((Deployment)link).setName(getBaseString()+((DeployedArtifact)target).getName());
		((Deployment)link).setLocation((DeploymentTarget)source);
		((Deployment)link).getDeployedArtifacts().add((DeployedArtifact)target);
		return true;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.helper.GraphEdgeHelper#deconnect(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param target 
	 * @param link 
	 * @param source 
	 * 
	 * @return 
	 */
	@Override
	public boolean deconnect(Element source, Element target, Element link) {
		Debug.debug(this,"deconnect(Element,Element,Element)", channel);	
		((Deployment)link).getSuppliers().remove((DeployedArtifact)target);
		return true;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.GraphEdgeFactory#canConnect(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param target 
	 * @param source 
	 * 
	 * @return 
	 */
	@Override
	public boolean canConnect(Element source,Element target){
		if((source instanceof DeploymentTarget)&& target==null){
			return true;
		}
		if ( (source != target) && 
		    ((source instanceof DeploymentTarget) && (target instanceof DeployedArtifact)) ) {
			return true;
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.GraphEdgeFactory#canCreateGraphElement(com.cea.papyrus.diagraminterchange2.di2.GraphElement)
	 */
	/**
	 * 
	 * 
	 * @param source 
	 * 
	 * @return 
	 */
	@Override
	public boolean canCreateGraphElement(GraphElement source){
		Debug.debug(this,"canCreateGraphElement(GraphElement)", channel);
		if (source instanceof Diagram ){
			return true;
		}
		if (source.getSemanticModel()!=null ){
			if (((Uml1SemanticModelBridge)source.getSemanticModel()).getElement()!=null){
				Element eltSource=((Uml1SemanticModelBridge)source.getSemanticModel()).getElement();			
				return canCreateUMLElement(eltSource);
			}
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.GraphEdgeFactory#createGraphEdge(org.eclipse.uml2.uml.Element, com.cea.papyrus.diagraminterchange2.di2.Diagram)
	 */
	/**
	 * 
	 * 
	 * @param umlElement 
	 * @param diagram 
	 * 
	 * @return 
	 */
	@Override
	public ArrayList createGraphEdge(Element umlElement, Diagram diagram){
		Debug.debug(this,"createGraphEdge(Element,Diagram)", channel);		
		Deployment de=(Deployment)umlElement;
		Iterator it = de.getDeployedArtifacts().iterator();
		while (it.hasNext()){
			GraphEdge ge=(GraphEdge)createGraphElement(umlElement, null, null, null);
			//look for UML connected UML element
			if (!(umlElement instanceof Deployment)){
				Debug.error(this, "EdgeDeploymentFactory.createGraphEdge: "+ umlElement+ "is not an Deployment!", channel);
			}
			DeployedArtifact deployedArtifact = (DeployedArtifact)it.next();
			Element umlsource = de.getLocation();
			Element umltarget = deployedArtifact;
			super.endCreateGraphElement(umlsource,umltarget,ge,diagram);
		}
	
		return new ArrayList();
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.GraphEdgeFactory#createGraphElement(org.eclipse.uml2.uml.Element, com.cea.papyrus.diagraminterchange2.di2.GraphElement, org.eclipse.draw2d.geometry.Point, org.eclipse.draw2d.geometry.Dimension)
	 */
	/**
	 * 
	 * 
	 * @param umlChild 
	 * @param size 
	 * @param location 
	 * @param parent 
	 * 
	 * @return 
	 */
	@Override
	public GraphElement createGraphElement(Element umlChild, GraphElement parent, Point location, Dimension size) {
		GraphElement graphElement=super.createGraphElement(umlChild, null, location, size);
		NodeHelper nf=new NodeHelper();
		// Name of the deployment
		GraphElement graphNode=nf.createGraphElement(null, graphElement, new Point(0, 10), null);
		graphNode.setFontSize(9);
		graphNode.setIsVisible(false);
	
		// Stereotype of the deployment
		graphNode=nf.createGraphElement(null, graphElement, new Point(0, 30), null);
		graphNode.setFontSize(9);
	
		// The parent has to be connected in last, because a event will be triggered.
		if(parent!=null){
			parent.getContained().add(graphElement);
		}
	
		return graphElement;	
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.GraphEdgeFactory#createUMLElement(java.lang.String, org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param umlParent 
	 * @param name 
	 * 
	 * @return 
	 */
	@Override
	public Element createUMLElement(String name, Element umlParent){
		Debug.debug(this,"createUMLElement(String,Element)", channel); //$NON-NLS-1$
		return ((DeploymentTarget)umlParent).createDeployment(name);		
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.GraphEdgeFactory#canCreateUMLElement(org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param umlParent 
	 * 
	 * @return 
	 */
	@Override
	public boolean canCreateUMLElement(Element umlParent) {
		if (umlParent instanceof DeploymentTarget) {
			return true;
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.GraphEdgeFactory#addUMLElement(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param element 
	 * @param umlParent 
	 * 
	 * @return 
	 */
	@Override
	public boolean addUMLElement(Element element, Element umlParent) {
		if (umlParent instanceof DeploymentTarget) {
			return ((DeploymentTarget)umlParent).getDeployments().add((Deployment)element);
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.GraphEdgeFactory#removeUMLElement(org.eclipse.uml2.uml.Element, org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param element 
	 * @param umlParent 
	 * 
	 * @return 
	 */
	@Override
	public boolean removeUMLElement(Element element, Element umlParent) {
		if (umlParent instanceof DeploymentTarget) {
			return ((DeploymentTarget)umlParent).getClientDependencies().remove(element);
		}
		return false;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.factories.GraphEdgeFactory#getBaseString()
	 */
	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	public String getBaseString() {
		return "Deployment_"; //$NON-NLS-1$
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.helper.NodeHelper#getNewUMLElementName(org.eclipse.uml2.uml.Element)
	 */
	/**
	 * 
	 * 
	 * @param umlParent 
	 * 
	 * @return 
	 */
	@Override
	public String getNewUMLElementName(Element umlParent) {
		String name = ""; //$NON-NLS-1$
	
		// i <10000: avoid infinite loops
		for(int i=0; i< 10001; i++ ) {
			name = getBaseString()+i;
			if(null == ((DeploymentTarget)umlParent).getDeployment(name)) {
				return name;
			}
		}
		return getBaseString()+"X"; //$NON-NLS-1$
	}

}
